/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using EXtremecode.Utils;
using EXtremecode.Common;
using System.Data;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Collections; 
using EXtremecode.DataAccessLayer;
using System.Text;

namespace EXtremecode.DataAccessLayer
{
	public enum CommandAction
	{
		Select,Insert,Delete,Update
	};
	
	public class DACommand:IPooledObject
	{
        DataAccessor m_da;
        private ObjectPool m_pool;
        IDbCommand  m_cmd;
        IDbCommand m_cmdTransaction;
        private string m_originalCommandText;
        private CommandAction m_commandAction;

        public CommandAction CommandAction
        {
            get { return m_commandAction; }
        }

        FieldInfoCollection m_fields = null;
		Hashtable htCacheFilter = new Hashtable();
		bool m_isOpen=false;
		
		
		
		//query extentions
        private string xtraWhereClause=string.Empty;
		private string strJoins=string.Empty;//inner joins or outer joins.
		
		
        //sorted by
        private string sortedBy=string.Empty;
		private bool isSortingTypeAscending=true;
        private bool needToRemakeSortedBy = true;
		
		//paging related
        private int pageNumber=0;//if pagenumber is zero, means return all records.
		private int pageSize=10;
        private long? totalRecords = null;

        
        
        public long? TotalRecords
        {
            get { return totalRecords; }
            set { totalRecords = value; }
        }
		private bool returnRowCount; //used to decide, whether select statement is being 
			//used for getting records or records count. ignore paging if this flag is set.

		private ArrayList m_deletedParamList=new ArrayList();

		public DACommand(IDbCommand cmd,DataAccessor da,IDbCommand cmdTransaction,CommandAction commandAction):this(cmd,da,cmdTransaction,null,commandAction){}
		public DACommand(IDbCommand cmd,DataAccessor da,IDbCommand cmdTransaction,FieldInfoCollection fields,CommandAction commandAction) 
		{
			
			if(cmd==null)return;
			m_cmd=cmd;
			m_fields=fields;
			m_cmdTransaction=cmdTransaction;
			m_da=da;
			m_originalCommandText=m_cmd.CommandText; 
			m_commandAction = commandAction;
		}
		
		public int ExecuteNoneQuery()
		{	
			if(!DataEncryptor.IsAllowed)
			{
				Logging.Logger.Write("Unregistered");
				return 0;
			}
			try
			{
				if(m_cmd==null)throw new Exception("Method is not available in the [offline] mode");
				SetValuesFromToken(false);
                if (ArrangeQuery(m_cmd))
                {
                    try
                    {

                        int records = 0;
                        OpenConnection();
                        foreach (IDbCommand cmd in m_da.GetInternalCommands(m_cmd))
                        {
                            records = cmd.ExecuteNonQuery();
                        }

                        RearrangeAfterSuccessfullExecution(m_cmd);
                        return records;
                    }
                    finally
                    {
                        CloseConnection();
                        AddDeletedParams(m_cmd);
                    }
                }
				return 0;
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(ex);
			}
			finally
			{
				Logging.Logger.Write();
			}

			
		}

		public int ExecuteNoneQueryForTransaction()
		{	
			if(!DataEncryptor.IsAllowed)
			{
				Logging.Logger.Write("Unregistered");
				return 0;
			}
			
			try
			{
				if(m_cmdTransaction==null)throw new Exception("Method is not available in the [offline] mode");
				SetValuesFromToken(true);
				m_cmdTransaction.Transaction=m_da.Transaction;
				m_cmdTransaction.Connection=m_da.TransactionConnection;
				if(ArrangeQuery(m_cmdTransaction))
				{
					try
					{
                        int records = 0;
                        foreach (IDbCommand cmd in m_da.GetInternalCommands(m_cmdTransaction))
                        {
                            records = cmd.ExecuteNonQuery();
                        }

						RearrangeAfterSuccessfullExecution(m_cmdTransaction);
						return records;
					}
					finally
					{
						AddDeletedParams(m_cmdTransaction);
					}
				}
				return 0;
		
			}
			catch(Exception ex)
			{
				DataAccessorCollection.Instance.Rollback();
				throw ex;
			}
		}

		public DADataReader GetDataReaderFromCache()
		{
			if(!DataEncryptor.IsAllowed)
			{
				Logging.Logger.Write("Unregistered");
				return null;
			}

			string whereClause = xtraWhereClause;
			string strAnd= (whereClause == string.Empty)? string.Empty: " and ";
			foreach(string hashKey in htCacheFilter.Keys)
			{
				string key=hashKey;
				bool toTrimed=false;
				bool fromTrimed=false;
				string val=htCacheFilter[key].ToString();
				string op = " = ";//operator used in where clause
				if(!m_fields.Contains(key))
				{
					//we assuming no field name in db could be
					//with these siffixes.
					//if key not found means, it may be with predefined suffix.
                    key = StringProcessor.RightTrim(key, Constants.ColumnSuffix.TO + Constants.ParamCustomType.CONDITIONAL , out toTrimed);
					if(!toTrimed)
					{
						//it may be with from suffix.
                        key = StringProcessor.RightTrim(key, Constants.ColumnSuffix.FROM + Constants.ParamCustomType.CONDITIONAL, out fromTrimed);
						
						if(!fromTrimed)
						{
							//now we have to throw exception because our assumtion has also been failed.
							//we are absorbing exception but logging it. because by mistake user can pass
							//invalid field in the form of page url.
							Logging.Logger.Write(new Exception(
								string.Format("[UC] field name [{0}] is not defined",key)));
						}
						else
						{
							op= " >= ";//fieldName >= value
						}
					}
					else
					{
						op= " <= ";//fieldName <= value
					}
				

					if(!m_fields.Contains(key))
					{
						//it may possible, trimmed field is also not defined 
						//we are absorbing exception but logging it. because by mistake user can pass
						//invalid field in the form of page url.
						Logging.Logger.Write(new Exception(
							string.Format("[UC] field name [{0}] is not defined",key)));

					}
					
				}

				FieldInfo field= m_fields[key];
				if(!fromTrimed && !toTrimed)
				{
					if(field.Type==Constants.UDTypes.TEXT)
					{
						op = " like "; 
					}
				}

				//enclosed by single qote check;
				string strSingleQote=string.Empty;
				if(field.Type==Constants.UDTypes.TEXT ||
					field.Type == Constants.UDTypes.DATE_TIME)
				{
					strSingleQote = "'";
				}

				whereClause += strAnd + key + op + strSingleQote + val + strSingleQote;
				strAnd = " and ";
				
			}
			ICachedDataSet icds = CacheRepository.Instance.CachedDataSet;
			DataTable dt=icds[m_fields.DataTableName];
			string sort=string.Empty; 
			if(SortedBy.Trim() != string.Empty)
			{
				sort= SortedBy +
					((isSortingTypeAscending)? " ASC ": " DESC ");
			}
			return new DADataReader(
				new DataRowReader(dt.Select(whereClause,sort),pageNumber,pageSize));

		}
		public DADataReader ExecuteReader()
		{
			if(!DataEncryptor.IsAllowed)
			{
				Logging.Logger.Write("Unregistered");
				return null;
			}
			
			try
			{
				if(m_cmd==null)throw new Exception("Method is not available in the [offline] mode");

				SetValuesFromToken(false);
				if(ArrangeQuery(m_cmd))
				{
                    try
                    {
                        IDataReader rdr = null;
                        OpenConnection();
                       
                        int recordsAffected = 0;
                        foreach (IDbCommand cmd in m_da.GetInternalCommands(m_cmd))
                        {
                            if (rdr != null)
                            {
                                rdr.Close();
                            }

                            rdr = cmd.ExecuteReader();
                            if (recordsAffected <= 0)
                            {
                                recordsAffected = rdr.RecordsAffected;
                            }
                        }
                        RearrangeAfterSuccessfullExecution(m_cmd);
                        DADataReader daReader = new DADataReader(rdr, m_cmd.Connection);
                        daReader.RecordsAffected = recordsAffected; //last query may contains only data.
                        return daReader;
                    }
                    catch
                    {
                        //connection will be closed only in case of exceptions otherwise,
                        //it will be closed with the closing of reader.
                        CloseConnection();
                        throw;
                    }
					finally
					{
						AddDeletedParams(m_cmd);
					}

				}
				else
					return new DADataReader(null);

			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(ex);
			}
			finally
			{
				Logging.Logger.Write();
			}
		}
		public DADataReader ExecuteReaderForTransaction()
		{
			if(!DataEncryptor.IsAllowed)
			{
				Logging.Logger.Write("Unregistered");
				return null;
			}
			
			try
			{
				if(m_cmdTransaction==null)throw new Exception("Method is not available in the [offline] mode");
				SetValuesFromToken(true);
				m_cmdTransaction.Transaction=m_da.Transaction;
				m_cmdTransaction.Connection = m_da.TransactionConnection; 	
				if(ArrangeQuery(m_cmdTransaction))
				{
					try
					{
                        IDataReader rdr = null;
                        int recordsAffected = 0;
                        foreach (IDbCommand cmd in m_da.GetInternalCommands(m_cmdTransaction))
                        {
                            if (rdr != null)
                            {
                                rdr.Close();
                            }

                            rdr = cmd.ExecuteReader();
                            if (recordsAffected <= 0)
                            {
                                recordsAffected = rdr.RecordsAffected;
                            }
                        }
						RearrangeAfterSuccessfullExecution(m_cmdTransaction);
                        DADataReader daReader = new DADataReader(rdr);
                        daReader.RecordsAffected = recordsAffected; //last query may contains only data.
                        return daReader;
					}
					finally
					{
						AddDeletedParams(m_cmdTransaction);
					}
					
				}
				else
					return new DADataReader(null);

			}
			catch(Exception ex)
			{
				DataAccessorCollection.Instance.Rollback();
				
				throw Logging.Logger.Write(ex);
			}
			finally
			{
				Logging.Logger.Write();
			}
		}
		private bool ArrangeUpdateQuery(IDbCommand cmd)
		{
			string timeStampParameterName=m_da.GetParameterName(StringProcessor.DBParameter(Configurations.Provider.TimestampColumnName));
			//Set the timestamp current value to DateTime.Now
			if(cmd.Parameters.Contains(timeStampParameterName))
			{
				((IDataParameter)cmd.Parameters[timeStampParameterName]).Value=DateTime.Now;  
			}
		
			string strColumnsQuery="";
			//Make Query
			foreach(IDataParameter param in cmd.Parameters)
			{
				
				if(param.SourceVersion==DataRowVersion.Current)
				{
					if(param.Value != null)
						strColumnsQuery += string.Format("{0} = {1} ,",m_da.GetEnclosedDbObject(param.SourceColumn),param.ParameterName);
					else if(!m_fields[param.SourceColumn].IsKey) 
						m_deletedParamList.Add(param);

				}
				
			}
			//Delete Notused params
			DeleteNotUsedParam(cmd);
			if(strColumnsQuery == "")return false;
			cmd.CommandText=string.Format(m_originalCommandText
                        ,strColumnsQuery.Trim(','));
			return true;

		}
		private bool ArrangeInsertQuery(IDbCommand cmd)
		{
			string timeStampParameterName=m_da.GetParameterName(StringProcessor.DBParameter(Configurations.Provider.TimestampColumnName));
			//Set the timestamp current value to DateTime.Now
			if(cmd.Parameters.Contains(timeStampParameterName))
			{
				((IDataParameter)cmd.Parameters[timeStampParameterName]).Value=DateTime.Now;  
			}
			
			string strColumnsNameQuery="";
			string strColumnsValueQuery="";
			
			//Make Query
			foreach(IDataParameter param in cmd.Parameters)
			{
				if(param.Value != null)
				{
					strColumnsNameQuery += string.Format("{0},",m_da.GetEnclosedDbObject(param.SourceColumn));
					strColumnsValueQuery +=param.ParameterName + ","; 
				}
				else
					m_deletedParamList.Add(param);
			}
			//Delete Not used param
			DeleteNotUsedParam(cmd);
			if(strColumnsNameQuery == "" || strColumnsValueQuery == "")return false;
			cmd.CommandText=string.Format(m_originalCommandText,strColumnsNameQuery.Trim(','),strColumnsValueQuery.Trim(','));
			return true;
		}
		private void RearrangeAfterSuccessfullExecution(IDbCommand cmd)
		{
			if(m_commandAction == CommandAction.Update)
			{
				string parameterName=m_da.GetParameterName(StringProcessor.DBParameter(Configurations.Provider.TimestampColumnName));
				//make the timestamp current value to original value 
				if(cmd.Parameters.Contains(parameterName) && cmd.Parameters.Contains(parameterName + "_" + Constants.ParamCustomType.CONDITIONAL))
				{
					((IDataParameter)m_cmd.Parameters[parameterName + "_" + Constants.ParamCustomType.CONDITIONAL]).Value =((IDataParameter)cmd.Parameters[parameterName]).Value;  
					((IDataParameter)m_cmdTransaction.Parameters[parameterName + "_" + Constants.ParamCustomType.CONDITIONAL]).Value =((IDataParameter)cmd.Parameters[parameterName]).Value;  

				}

			}
			


		}
		private bool ArrangeQuery(IDbCommand cmd)
		{
			m_deletedParamList.Clear();
			if(m_commandAction == CommandAction.Delete)
				return ArrangeDeleteQuery(cmd); 
			else if(m_commandAction == CommandAction.Update)
				return ArrangeUpdateQuery(cmd);
			else if(m_commandAction == CommandAction.Insert)
				return ArrangeInsertQuery(cmd);
			else if(m_commandAction == CommandAction.Select)
				return ArrangeSelectQuery(cmd);
			else
				return false;

		}
		public void ArrangeQuery()
		{
			ArrangeQuery(m_cmd);
		}
		public void ArrangeQuery(bool transactionBased)
		{
			if(transactionBased)
				ArrangeQuery(m_cmdTransaction);
			else
				ArrangeQuery(m_cmd);
		}
		public void RearrangeAfterExecution(bool transactionBased)
		{
			if(transactionBased)
				RearrangeAfterSuccessfullExecution(m_cmdTransaction);
			else
				RearrangeAfterSuccessfullExecution(m_cmd);
		}
		public void RearrangeAfterExecution()
		{
			RearrangeAfterSuccessfullExecution(m_cmd);
		}
		public void AddDeletedParams(bool transactionBased)
		{
			if(transactionBased)
				AddDeletedParams(m_cmdTransaction);
			else
				AddDeletedParams(m_cmd);
		}
		public void AddDeletedParams()
		{
			AddDeletedParams(m_cmd);
		}

		private bool ArrangeDeleteQuery(IDbCommand cmd)
		{
			StringBuilder sbQueryWhereClause=new StringBuilder();
			doArrangementCommonForSelectNDeleteQuery(cmd,sbQueryWhereClause,m_fields.TableName); 
			if(sbQueryWhereClause.Length == 0) return true;
			cmd.CommandText= m_originalCommandText + " and " + sbQueryWhereClause.ToString();
			return true;
		}
		private void doArrangementCommonForSelectNDeleteQuery(IDbCommand cmd,StringBuilder sbQueryWhereClause,string dbObjectName)
		{
			string strAnd="";
			for(int i=0; i<cmd.Parameters.Count; i++)
			{
				IDataParameter param=cmd.Parameters[i] as IDataParameter;
				FieldInfo field=m_fields[param.SourceColumn] as FieldInfo;
				if(param.SourceVersion==DataRowVersion.Current)
				{
                    if (param.Value != null && param.Value != DBNull.Value)
                    {

                        if (field.Type == Constants.UDTypes.TEXT)
                        {
                            sbQueryWhereClause.Append(strAnd + string.Format("( {0}.{1} like {2} or {2} is null )",
                                m_da.GetEnclosedDbObject(dbObjectName), m_da.GetEnclosedDbObject(field.Name), param.ParameterName));
                        }
                        else
                        {
                            if (field.IsRange)
                            {
                                string parameterName = m_da.GetParameterName(StringProcessor.DBParameter(param.SourceColumn));

                                string equalParamName =
                                     string.Format("{0}{1}_{2}"
                                        , parameterName
                                        , string.Empty
                                        , Constants.ParamCustomType.CONDITIONAL);

                                string fromParamName =
                                    string.Format("{0}{1}_{2}"
                                       , parameterName
                                       , Constants.ColumnSuffix.FROM
                                       , Constants.ParamCustomType.CONDITIONAL);


                                string toParamName =
                                    string.Format("{0}{1}_{2}"
                                       , parameterName
                                       , Constants.ColumnSuffix.TO
                                       , Constants.ParamCustomType.CONDITIONAL);


                                if (param.ParameterName == equalParamName)
                                {
                                    sbQueryWhereClause.Append(strAnd + string.Format("( {0}.{1} = {2} or {2} is null )",
                                        m_da.GetEnclosedDbObject(dbObjectName), m_da.GetEnclosedDbObject(field.Name),
                                        param.ParameterName));
                                    strAnd = " And ";
                                }
                                else if (param.ParameterName == fromParamName)
                                {
                                    sbQueryWhereClause.Append(strAnd + string.Format("(  {0}.{1} >= {2} or {2} is null )",
                                        m_da.GetEnclosedDbObject(dbObjectName), m_da.GetEnclosedDbObject(field.Name),
                                        param.ParameterName));
                                    strAnd = " And ";
                                }
                                else if (param.ParameterName == toParamName)
                                {
                                    sbQueryWhereClause.Append(strAnd + string.Format("(  {0}.{1} <= {2} or {2} is null )",
                                        m_da.GetEnclosedDbObject(dbObjectName), m_da.GetEnclosedDbObject(field.Name),
                                        param.ParameterName));
                                    strAnd = " And ";
                                }

                            }
                            else
                            {
                                sbQueryWhereClause.Append(strAnd + string.Format("(  {0}.{1} = {2} or {2} is null )",
                                    m_da.GetEnclosedDbObject(dbObjectName), m_da.GetEnclosedDbObject(field.Name),
                                    param.ParameterName));
                            }
                        }
                        strAnd = " And ";

                    }
                    else
                    {
                        if (param.Value == DBNull.Value)
                        {
                            sbQueryWhereClause.Append(strAnd + string.Format(" {0}.{1} is null ",
                                    m_da.GetEnclosedDbObject(dbObjectName), m_da.GetEnclosedDbObject(field.Name)));
                            strAnd = " And ";
                        }
                        m_deletedParamList.Add(param);
                    }

				}

			}
			DeleteNotUsedParam(cmd);

			//add xtra where clause.
			if(xtraWhereClause != null && xtraWhereClause != string.Empty)
			{
				sbQueryWhereClause.Append(strAnd + string.Format("({0})",xtraWhereClause));
			}

		}
		private bool ArrangeSelectQuery(IDbCommand cmd)
		{
            cmd.CommandText = string.Format(m_originalCommandText,strJoins);
            StringBuilder sbQueryWhereClause=new StringBuilder();
			doArrangementCommonForSelectNDeleteQuery(cmd,sbQueryWhereClause,m_fields.ViewName); 
			
			//where clause.
			if(sbQueryWhereClause.Length > 0)
			{
                cmd.CommandText = cmd.CommandText + " and " + sbQueryWhereClause.ToString();
			}
			
			//row count
            if (returnRowCount)
            {
                string truncatedTest = string.Format("Select {0}.*", m_da.GetEnclosedDbObject(m_fields.ViewName));
                string str = cmd.CommandText.Substring(cmd.CommandText.IndexOf(truncatedTest) + truncatedTest.Length);
                cmd.CommandText = "Select count(*) as recordsCount" + str;
                return true; //no need to use paging and sorting
            }
            else
            {

                //paging
                if (pageNumber > 0)
                {
                    cmd.CommandText = m_da.GeneratePagingQuery(cmd.CommandText, SortedBy,
                        isSortingTypeAscending, pageNumber, pageSize, totalRecords);
                }
                else
                {
                    //---sorted by.
                    if (SortedBy.Trim() != string.Empty)
                    {
                        string sortingType = (isSortingTypeAscending) ? " ASC " : " DESC ";
                        cmd.CommandText += " order by " +
                            SortedBy.Replace(",", sortingType + ",") + sortingType;

                    }
                }
            }
			return true;

			
		}
		private void DeleteNotUsedParam(IDbCommand cmd)
		{
			foreach(object obj in m_deletedParamList)
			{
				cmd.Parameters.Remove(obj);
			}
		}
		private void AddDeletedParams(IDbCommand cmd)
		{
			//Add Deleted Param
			foreach(object obj in m_deletedParamList)
			{
				cmd.Parameters.Add(obj);
			}
		}
		public IDbCommand ClassicCommand
		{ 
			get
			{
				return m_cmd;
			}
		}
		public object this[string fieldName]
		{
			get
			{
				if(m_cmd==null)
				{
					return null;
				}

				object val=DBNull.Value;
				string parameterName=m_da.GetParameterName(StringProcessor.DBParameter(fieldName));
				if(m_cmd.Parameters.Contains(parameterName)) 
				{
					val= ((IDataParameter)m_cmd.Parameters[parameterName]).Value;
				}
                else if (m_cmd.Parameters.Contains(parameterName + ColumnSuffix.KeyParam)) //parameters may have suffix
                {
                    val = ((IDataParameter)m_cmd.Parameters[parameterName + ColumnSuffix.KeyParam]).Value;
                }

				return val;
			}
			set
			{
				//cache will work in offline mode.
				if(htCacheFilter.Contains(fieldName))
				{
					htCacheFilter[fieldName]=value;  
				}
				else
				{
					htCacheFilter.Add(fieldName,value);
				}
		
				if(m_cmd!=null)
				{	
					//only for online.	
					if(value == null) 
					{
						value=DBNull.Value; 
					}

					string parameterName=m_da.GetParameterName(StringProcessor.DBParameter(fieldName));
					if(m_cmd.Parameters.Contains(parameterName))
					{
						((IDataParameter)m_cmd.Parameters[parameterName]).Value=value;
					}
                    else if (m_cmd.Parameters.Contains(parameterName + ColumnSuffix.KeyParam))//parameters may have suffix
                    {
                        ((IDataParameter)m_cmd.Parameters[parameterName + ColumnSuffix.KeyParam]).Value = value;
                    }


					if(m_cmdTransaction.Parameters.Contains(parameterName))
					{
						((IDataParameter)m_cmdTransaction.Parameters[parameterName]).Value=value;
					}
                    else if (m_cmdTransaction.Parameters.Contains(parameterName + ColumnSuffix.KeyParam))//parameters may have suffix
                    {
                        ((IDataParameter)m_cmdTransaction.Parameters[parameterName + ColumnSuffix.KeyParam]).Value = value;
                    }
				}

			}
		}
        public void CleanParams()
        {
            foreach (string fieldName in m_fields.Keys)
            {
                CleanParam(fieldName);
            }
        }
		public void  CleanParam(string fieldName)
		{
			string parameterName=m_da.GetParameterName(StringProcessor.DBParameter(fieldName));
            if (m_cmd.Parameters.Contains(parameterName))
            {
                ((IDataParameter)m_cmd.Parameters[parameterName]).Value = null;
            }
            if (m_cmdTransaction.Parameters.Contains(parameterName))
            {
                ((IDataParameter)m_cmdTransaction.Parameters[parameterName]).Value = null;
            }

			if(htCacheFilter.ContainsKey(fieldName))
			{
				htCacheFilter.Remove(fieldName);
			}


		}
		private void CloseConnection()
		{
			if(m_cmd==null)return;
			if(m_isOpen)
			{
				m_cmd.Connection.Close();
				m_isOpen=false;
			}
		}
		
		private void OpenConnection()
		{
			if(m_cmd==null)return;
            if (!m_isOpen)
            {
                m_cmd.Connection.Open();
                m_isOpen = true;
            }
            else
            {
                //we are supposing, current connection is getting used by
                //dada reader, and it will be reader resoponsibilitiy to close it.
                m_cmd.Connection = m_da.CreateNewConnection();
                m_cmd.Connection.Open();
            }
		}
		private void  SetValuesFromToken(bool transactionBased)
		{
			try
			{
				if(m_commandAction != CommandAction.Insert)return;
				DataAccessor da=DataAccessorCollection.DefaultAccessor; 
				foreach(FieldInfo field in m_fields.TokenFields)
				{
					this[field.Name]=da.GetTokenValue(field.TokenId,transactionBased,true);
				}
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(ex);
			}
			finally
			{
				//Logging.Logger.Write();
			}
		}
		public IDbTransaction Transaction
		{
			get
			{
				if(m_cmdTransaction==null)return null;
				return m_cmdTransaction.Transaction;
			}
			set
			{
				if(m_cmdTransaction==null)return;
				m_cmdTransaction.Transaction=value;
			}
		}

		public string WhereClause
		{
			get
			{
				return xtraWhereClause; 
			}
			set
			{
				xtraWhereClause =value;
			}
		}
		public string Joins
		{
			get
			{
				return strJoins;
			}
			set
			{
				strJoins=value;
			}
		}
		public bool ReturnRowCount 
		{
			get
			{
				return returnRowCount;
			}
			set
			{
				returnRowCount=value;
			}
		}	

		public int PageSize
		{
			get
			{
				return pageSize;
			}
			set
			{
				pageSize=value;
			}
		}
	
		public int PageNumber
		{
			get
			{
				return pageNumber;
			}
			set
			{
				pageNumber=value;
			}
		}

		public string SortedBy
		{
			get
			{
                if (needToRemakeSortedBy)
                {
                    string val = (sortedBy == null) ?
                        string.Empty :
                        sortedBy.Trim();


                    string[] sortedByArray = new string[0];
                    if (val != string.Empty)
                    {
                        sortedByArray = val.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
                    }

                    string keyFieldsString = string.Empty;
                    if (m_fields.KeyFields.Count > 0)
                    {
                        //Making Sorted Claus for Keys.
                        string qoma = string.Empty;
                        foreach (FieldInfo field in m_fields.KeyFields)
                        {
                            bool noNeedToAdd = false;
                            foreach (string sortedByField in sortedByArray)
                            {
                                if (sortedByField.Trim().ToUpper() == field.Name.ToUpper())
                                {
                                    //if field field value found in sortedByList, then no need to this field again in appended
                                    //sorted list.
                                    noNeedToAdd = true;
                                    break;
                                }
                            }
                            if (noNeedToAdd)
                            {
                                continue;
                            }
                            keyFieldsString += qoma + field.Name;
                            qoma = " , ";
                        }

                    }
                    sortedBy = (val == string.Empty) ?
                        keyFieldsString :
                        (keyFieldsString == string.Empty) ?
                            val :
                            val + " , " + keyFieldsString;
                    needToRemakeSortedBy = false;

                }
                return sortedBy;
			}
			set
			{
				sortedBy=value;
                needToRemakeSortedBy = true;
			}
		}
		public bool IsSortingTypeAscending
		{
			get
			{
				return isSortingTypeAscending;
			}
			set
			{
				isSortingTypeAscending=value;
			}
		}

        #region IPooledObject Members

        public ObjectPool Pool
        {
            get
            {
                return m_pool;
            }
            set
            {
                m_pool = value;
            }
        }

        #endregion
    }

}
